package com.curvebreakers.wheresmystuff.model;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Represents an entry that can display its information.
 * @author evan.cahill
 */
public class Entry implements Parcelable {
	
	private int id, userId, reward;
	private String title, description;
	private Category category;
	private EntryType entryType;
	private boolean resolved;
	private Date date;
	private String userEmail;
	private String zipCode;	
	
	public Entry(int userId, String title, String description, Category category, EntryType type, int reward, boolean resolved, Date date, String userEmail, String zipCode) {
		this(-1, userId, title, description, category, type, reward, resolved, date, userEmail, zipCode);
	}
	
	private Entry(int id, int userId, String title, String description, Category category, EntryType entryType, int reward, boolean resolved, Date date, String userEmail, String zipCode) {
		this.id = id;
		this.userId = userId;
		this.title = title;
		this.description = description;
		this.category = category;
		this.entryType = entryType;
		this.reward = reward;
		this.resolved = resolved;
		this.date = date;
		this.userEmail = userEmail;
		this.zipCode = zipCode;
	}
	
	/**
	 * Parses the given <code>JSONObject</code> and returns the <code>Entry</code> that it
	 * represents.
	 * @param json The JSON object that encodes a user.
	 * @return The <code>User</code> represented by the JSON object.
	 */
	public static Entry createFromJSON(JSONObject json) {
		try {
			DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss", Locale.ENGLISH);
			formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
			Date d = formatter.parse(json.getString("date_posted"));
			Builder b = new Entry.Builder()
					.id(json.getInt("id"))
					.userId(json.getInt("user_id"))
					.title(json.getString("title"))
					.description(json.getString("description"))
					.category(Category.getCategory(json.getString("category")))
					.entryType(EntryType.getEntryType(json.getString("type")))
					.reward(json.getInt("reward"))
					.resolved(json.getString("resolved").equals("t"))
					.date(d)
					.userEmail(json.getString("email"))
					.zipCode(json.getString("zip_code"));
			return b.build();//new Entry(json.getInt("id"), json.getInt("user_id"), json.getString("title"), json.getString("description"), Category.getCategory(json.getString("category")),EntryType.getEntryType(json.getString("type")), json.getInt("reward"), json.getString("resolved").equals("t"), d, json.getString("email"), json.getString("zip_code"));
		} catch (Exception e) {
			System.out.println(e);
			return null;
		}
	}
	
	/**
	 * Iterates through a JSONArray and calls createFromJSON on each entry.
	 * @param array
	 * @return A List containing the Entries in the given array.
	 */
	public static List<Entry> createListFromJSON(JSONArray array) {
		List<Entry> list = new ArrayList<Entry>(array.length());
		for (int i=0; i<array.length(); i++) {
			Entry entry;
			try {
				entry = Entry.createFromJSON(array.getJSONObject(i));
			} catch (JSONException e) {
				entry = null;
				e.printStackTrace();
			}
			if (entry!=null) list.add(entry);
		}
		return list;
	}
	
	
	//Begin Getters and Setters

	/**
	 * @return the id
	 */
	public int getId() {
		return id;
	}

	/**
	 * @return the userId
	 */
	public int getUserId() {
		return userId;
	}

	/**
	 * @return the title
	 */
	public String getTitle() {
		return title;
	}
	

	/**
	 * @param title the title to set
	 */
	public void setTitle(String title) {
		this.title = title;
	}
	

	/**
	 * @return the description
	 */
	public String getDescription() {
		return description;
	}
	

	/**
	 * @param description the description to set
	 */
	public void setDescription(String description) {
		this.description = description;
	}
	

	/**
	 * @return the category
	 */
	public Category getCategory() {
		return category;
	}
	

	/**
	 * @param category the category to set
	 */
	public void setCategory(Category category) {
		this.category = category;
	}

	/**
	 * @return the entry type
	 */
	public EntryType getEntryType() {
		return entryType;
	}

	/**
	 * @param entryType the entry type to set
	 */
	public void setEntryType(EntryType entryType) {
		this.entryType = entryType;
	}
	
	/**
	 * @return the resolved status of the entry
	 */
	public boolean isResolved() {
		return resolved;
	}
	
	/**
	 * @param resolved the status of the entry
	 */
	public void setResolved(boolean resolved) {
		this.resolved = resolved;
	}
	
	/**
	 * @return The current date
	 */
	public Date getDate() {
		return date;
	}
	
	/**
	 * @return the properly formatted date string to be passed into the database query
	 */
	public String getDateString() {
		
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		Calendar now = Calendar.getInstance();
		now.setTime(new Date());
		DateFormat formatter;
		if (c.get(Calendar.YEAR) == now.get(Calendar.YEAR))
			formatter = new SimpleDateFormat("MMMM d", Locale.ENGLISH);
		else
			formatter = new SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH);
		formatter.setTimeZone(TimeZone.getDefault());
		return formatter.format(date);
	}
	
	/**
	 * @return the properly formatted string with date and time to be passed into 
	 * the database query
	 */
	public String getDateTimeString() {
		DateFormat formatter = new SimpleDateFormat("MMM d, yyyy h:mm a", Locale.ENGLISH);
		formatter.setTimeZone(TimeZone.getDefault());
		return formatter.format(date);
	}
	
	/**
	 * @return the userEmail
	 */
	public String getUserEmail() {
		return userEmail;
	}
	
	/**
	 * @return the string representing the entry's status
	 */
	public String getStatusString() {
		return resolved ? "Resolved" : "Unresolved";
	}
	
	/**
	 * @return the entry's reward value
	 */
	public int getReward() {
		return reward;
	}
	
	/**
	 * @return the entry's zip-code
	 */
	public String getZipCode() {
		return zipCode;
	}
	
	/**
	 * @return the entry's title
	 */
	@Override
	public String toString() {
		return title;
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeInt(id);
		dest.writeInt(userId);
		dest.writeString(title);
		dest.writeString(description);
		dest.writeString(category.toString());
		dest.writeString(entryType.toString());
		dest.writeInt(reward);
		dest.writeByte((byte) (resolved ? 1 : 0));
		dest.writeLong(date.getTime());
		dest.writeString(userEmail);
		dest.writeString(zipCode);
	}
	
	public static Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator<Entry>() {
		public Entry createFromParcel(Parcel in) {
			Entry.Builder b = new Entry.Builder()
				.id(in.readInt())
				.userId(in.readInt())
				.title(in.readString())
				.description(in.readString())
				.category(Category.getCategory(in.readString()))
				.entryType(EntryType.getEntryType(in.readString()))
				.reward(in.readInt())
				.resolved(in.readByte() == 1)
				.date(new Date(in.readLong()))
				.userEmail(in.readString())
				.zipCode(in.readString());
			return b.build();
        }

        public Entry[] newArray(int size) {
            return new Entry[size];
        }
	};
	
	public static class Builder {
		private int id, userId, reward;
		private String title, description;
		private Category category;
		private EntryType entryType;
		private boolean resolved;
		private Date date;
		private String userEmail;
		private String zipCode;
		
		public Builder() {
			this.id = -1;
			this.date = new Date();
		}
		
		public Builder id(int id) {
			this.id = id;
			return this;
		}
		
		public Builder userId(int userId) {
			this.userId = userId;
			return this;
		}
		
		public Builder title(String title) {
			this.title = title;
			return this;
		}
		
		public Builder description(String description) {
			this.description = description;
			return this;
		}
		
		public Builder category(Category category) {
			this.category = category;
			return this;
		}
		
		public Builder entryType(EntryType entryType) {
			this.entryType = entryType;
			return this;
		}
		
		public Builder reward(int reward) {
			this.reward = reward;
			return this;
		}
		
		public Builder resolved(boolean resolved) {
			this.resolved = resolved;
			return this;
		}
		
		public Builder date(Date date) {
			this.date = date;
			return this;
		}
		
		public Builder userEmail(String userEmail) {
			this.userEmail = userEmail;
			return this;
		}
		
		public Builder zipCode(String zipCode) {
			this.zipCode = zipCode;
			return this;
		}
		
		public Entry build(){
			return new Entry(id, userId, title, description, category, entryType, reward, resolved, date, userEmail, zipCode);
		}
	}

}
